package at.codebase.web.servlets.item;

import java.util.HashMap;

import at.codebase.db.entities.EItemFeedback.EItemFeedbackRating;

/**
 * A Input Status is used to verify a Argument/Input. It proves the raw data and
 * converts it to the needed type.
 * 
 * @author Lukas Pfeifhofer <lukas.pfeifhofer@devlabs.pro>
 * 
 */
public class ItemInputStatus {
	
	public static class InputStatusFeedbackRating extends InputStatus<String, EItemFeedbackRating> {
		public InputStatusFeedbackRating(String rawValue) {
			super(rawValue);
		}

		@Override
		public void compile() {
			if (rawValue != null) {
				String raw = rawValue.trim();
				try {
					int valueI = Integer.parseInt(raw);
					if (valueI >= 1 && valueI <= 5) {
						switch (valueI) {
						case 1:
							value = EItemFeedbackRating.RUBY_1;
							break;
						case 2:
							value = EItemFeedbackRating.RUBY_2;
							break;
						case 3:
							value = EItemFeedbackRating.RUBY_3;
							break;
						case 4:
							value = EItemFeedbackRating.RUBY_4;
							break;
						case 5:
							value = EItemFeedbackRating.RUBY_5;
							break;
						}
						error = false;
						return;
					}
				} catch (NumberFormatException e) {
				}
			}
			error = true;
		}
	}	
	
	public static class InputStatusFeedbackText extends
			InputStatus<String, String> {

		public InputStatusFeedbackText(String rawValue) {
			super(rawValue);
		}

		@Override
		public void compile() {
			if (rawValue != null) {
				String raw = rawValue.trim();
				if (raw.matches("(.|\\n|\\r)+")) {
					error = false;
					value = raw;
					return;
				}
			}
			error = true;
		}

	}

	public static class InputStatusTitle extends InputStatus<String, String> {

		public InputStatusTitle(String rawValue) {
			super(rawValue);
		}

		@Override
		public void compile() {
			if (rawValue != null) {
				String raw = rawValue.trim();
				if (raw.matches("[a-zA-Z0-9äöüÄÖÜ\\s]{1,92}")) {
					error = false;
					value = raw;
					return;
				}
			}
			error = true;
		}

	}

	public static class InputStatusPrice extends InputStatus<String, Double> {

		public InputStatusPrice(String rawValue) {
			super(rawValue);
		}

		@Override
		public void compile() {
			if (rawValue != null) {
				String raw = rawValue.trim();
				if (raw.matches("[0-9]+(\\.[0-9]{0,2})?")) {
					try {
						double valueD = Double.parseDouble(raw);
						if (valueD > 0 && valueD < 2147483648.0d) {
							error = false;
							value = new Double(valueD);
							return;
						}
					} catch (NumberFormatException e) {
					}
				}
			}
			error = true;
		}

	}
	
	public static class InputStatusLatitude extends InputStatus<String, Double> {

		public InputStatusLatitude(String rawValue) {
			super(rawValue);
		}

		@Override
		public void compile() {
			if (rawValue != null) {
				String raw = rawValue.trim();
				if (raw.matches("(-)?[0-9]+(\\.[0-9]+)?")) {
					try {
						double valueD = Double.parseDouble(raw);
						if (Math.abs(valueD) <= 90) {
							error = false;
							value = new Double(valueD);
							return;
						}
					} catch (NumberFormatException e) {
					}
				}
			}
			error = true;
		}

	}
	
	public static class InputStatusLongitude extends InputStatus<String, Double> {

		public InputStatusLongitude(String rawValue) {
			super(rawValue);
		}

		@Override
		public void compile() {
			if (rawValue != null) {
				String raw = rawValue.trim();
				if (raw.matches("(-)?[0-9]+(\\.[0-9]+)?")) {
					try {
						double valueD = Double.parseDouble(raw);
						if (Math.abs(valueD) <= 180) {
							error = false;
							value = new Double(valueD);
							return;
						}
					} catch (NumberFormatException e) {
					}
				}
			}
			error = true;
		}

	}

	public static class InputStatusDescription extends
			InputStatus<String, String> {

		public InputStatusDescription(String rawValue) {
			super(rawValue);
		}

		@Override
		public void compile() {
			if (rawValue != null) {
				String raw = rawValue.trim();
				if (raw.matches("(.|\\n|\\r)+")) {
					error = false;
					value = raw;
					return;
				}
			}
			error = true;
		}

	}

	public static class InputStatusExpirationDate extends
			InputStatus<String, Integer> {

		static HashMap<String, Integer> timePeriods = new HashMap<String, Integer>();

		static {
			// First is the option value, second is the offset time in seconds.
			// hour=3600, day=86 400, week=604 800
			// Keys will be sorted alphabetically
			timePeriods.put("amin1", new Integer(60));
			timePeriods.put("day3", new Integer(259200));
			timePeriods.put("day5", new Integer(432000));
			timePeriods.put("week1", new Integer(604800));
			timePeriods.put("week2", new Integer(1209600));
			timePeriods.put("week3", new Integer(1814400));
		}

		public InputStatusExpirationDate(String rawValue) {
			super(rawValue);
		}

		@Override
		public void compile() {
			if (rawValue != null) {
				String raw = rawValue.trim();
				Integer expirationOffset = timePeriods.get(raw);
				if (expirationOffset != null) {
					error = false;
					value = expirationOffset;
					return;
				}
			}
			error = true;
		}

	}

	public static class InputStatusVoid extends InputStatus<String, String> {

		public InputStatusVoid(String defaultValue) {
			super(defaultValue);
			this.value = "";
		}

		public InputStatusVoid() {
			super("");
			this.value = "";
		}

		@Override
		public void compile() {

		}

	}

	public static abstract class InputStatus<I, E> {
		I rawValue;
		E value;
		boolean error;

		public InputStatus(I rawValue) {
			this.rawValue = rawValue;
			this.value = null;
			this.error = false;

			if (this.rawValue == null) {
				this.error = true;
			}
		}

		public String getRawString() {
			if (rawValue == null)
				return "";
			return rawValue.toString();
		}

		public boolean isError() {
			return error;
		}

		public abstract void compile();

		public E getValue() {
			return value;
		}
	}
}
